package com.sky.service.impl;

import com.sky.dto.SalesTop10ItemDTO;
import com.sky.exception.BaseException;
import com.sky.service.OrderService;
import com.sky.service.ReportService;
import com.sky.service.UserService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserService userService;
    @Autowired
    private WorkspaceService workspaceService;

    @Override
    public TurnoverReportVO turnoverReport(LocalDate begin, LocalDate end) {
        // 生成x轴的时间数据
        List<LocalDate> dateList = new ArrayList<>();
        while(begin.isBefore(end)){
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        dateList.add(end);
        // 遍历每一天，查询当天的订单已经完成的金额
        List<Double> turnOverList = new ArrayList<>();
        for (LocalDate localDate : dateList) {
            // startTime：就是年月日00:00:00
            LocalDateTime startTime = LocalDateTime.of(localDate, LocalTime.of(0, 0, 0));
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.of(23, 59, 59));
            double turnOver = orderService.turnOver(startTime, endTime);
            turnOverList.add(turnOver);
        }
        // 组装结果数据
        TurnoverReportVO vo = new TurnoverReportVO();
        vo.setDateList(
                dateList.stream()
                        .map(date->date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                        .collect(Collectors.joining(",")));
        vo.setTurnoverList(
                turnOverList.stream()
                        .map(turnOver->String.valueOf(turnOver))
                        .collect(Collectors.joining(","))
        );
        return vo;
    }

    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end) {
        // 生成x轴的时间数据
        List<LocalDate> dateList = new ArrayList<>();
        while(begin.isBefore(end)){
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        dateList.add(end);
        // 遍历每一天，查询新用户 和 总的用户数量
        StringBuilder newUsers = new StringBuilder();
        StringBuilder totalUsers = new StringBuilder();
        for (LocalDate localDate : dateList) {
            // 当天的开始时间
            LocalDateTime startTime = LocalDateTime.of(localDate, LocalTime.of(0, 0, 0));
            // 当天的终止时间
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.of(23, 59, 59));
            // 查询当天新用户的数量
            int newUserCount = userService.countNewUser(startTime, endTime);
            // 查询截至到当前时间总的用户数量
            int totalUserCount = userService.countTotalUser(endTime);
            // 构造数据
            if(newUsers.length() > 0){
                newUsers.append(",");
            }
            newUsers.append(newUserCount);

            if(totalUsers.length()>0){
                totalUsers.append(",");
            }
            totalUsers.append(totalUserCount);
        }
        // 封装vo返回
        UserReportVO vo = new UserReportVO();
        vo.setDateList(
                        dateList.stream()
                                .map(date->date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                                .collect(Collectors.joining(","))
        );
        vo.setNewUserList(newUsers.toString());
        vo.setTotalUserList(totalUsers.toString());
        return vo;
    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        // 生成x轴的时间数据
        List<LocalDate> dateList = new ArrayList<>();
        while(begin.isBefore(end)){
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        dateList.add(end);
        // 总的订单数
        int total = 0;
        // 总的有效订单数
        int totalValid = 0;
        // 每天的总的订单数
        List<Integer> dayTotalList = new ArrayList<>();
        // 每天的有效的订单数
        List<Integer> dayValidList = new ArrayList<>();
        // 遍历每一天
        for (LocalDate localDate : dateList) {
            // 当天的开始时间
            LocalDateTime startTime = LocalDateTime.of(localDate, LocalTime.MIN);
            // 当天的终止时间
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);
            // 查询当天的订单的总数
            int dayTotal = orderService.countTotalOrders(startTime, endTime);
            // 查询当天的有效订单数
            int dayValid = orderService.countValidOrders(startTime, endTime);
            // 保存到list
            dayTotalList.add(dayTotal);
            dayValidList.add(dayValid);
            // 累加到合计
            total += dayTotal;
            totalValid += dayValid;
        }
        // 构造返回数据
        OrderReportVO vo = new OrderReportVO();
        vo.setValidOrderCount(totalValid);
        vo.setTotalOrderCount(total);
        vo.setOrderCompletionRate(total<=0?0:totalValid * 1.0 / total);
        vo.setDateList(join(dateList));
        vo.setValidOrderCountList(join(dayValidList));
        vo.setOrderCountList(join(dayTotalList));
        return vo;
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        List<SalesTop10ItemDTO> list = orderService.salesTop10(begin, end);
        if(CollectionUtils.isEmpty(list)){
            return new SalesTop10ReportVO();
        }
        // 封装成SalesTop10ReportVO
        SalesTop10ReportVO vo = new SalesTop10ReportVO();
        // 名称
        String names = list.stream().map(SalesTop10ItemDTO::getName).collect(Collectors.joining(","));
        vo.setNameList(names);
        // 销量
        String numbers = list.stream().map(SalesTop10ItemDTO::getSale).map(e->String.valueOf(e)).collect(Collectors.joining(","));
        vo.setNumberList(numbers);
        return vo;
    }

    private <T> String join(List<T> list){
        return list.stream().map((e)->String.valueOf(e)).collect(Collectors.joining(","));
    }

    @Override
    public void export(HttpServletResponse response) {
        // 查询30天的汇总数据
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusDays(30).toLocalDate().atStartOfDay();
        BusinessDataVO businessDataVO = workspaceService.businessDate(startTime, endTime);
        log.info("businessDataVO：{}", businessDataVO.toString());
        // 查询每一天的明细数据
        List<BusinessDataVO> dayVoList = new ArrayList<>();
        while(startTime.isBefore(endTime)){
            LocalDateTime dayEnd = startTime.plusHours(24).minusSeconds(1);
            BusinessDataVO dayVo  = workspaceService.businessDate(startTime, dayEnd);
            dayVoList.add(dayVo);
            log.info("startTime:{}, dayVo：{}", startTime, dayVo);
            startTime = startTime.plusDays(1);
        }
        try{
            // 读取excel模板
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表模板.xlsx");
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            // 填充模板
            XSSFSheet sheet = workbook.getSheetAt(0);
            // 填充30天的汇总数据
            XSSFRow row3 = sheet.getRow(3);
            XSSFRow row4 = sheet.getRow(4);
            row3.getCell(2).setCellValue(businessDataVO.getTurnover()+"");
            row3.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate()+"");
            row3.getCell(6).setCellValue(businessDataVO.getNewUsers()+"");
            row4.getCell(2).setCellValue(businessDataVO.getValidOrderCount()+"");
            row4.getCell(4).setCellValue(businessDataVO.getUnitPrice()+"");
            // 填充某一天的汇总数据
            int i= 0;
            startTime = endTime.minusDays(30).toLocalDate().atStartOfDay();
            for (BusinessDataVO dayVo : dayVoList) {
                XSSFRow row = sheet.getRow(7 + i);
                if(row == null){
                    row = sheet.createRow(7 + i);
                    row.setHeight((short)500);
                    XSSFCellStyle cellStyle = workbook.createCellStyle();
                    cellStyle.setBorderBottom(BorderStyle.THIN);
                    cellStyle.setBottomBorderColor(new XSSFColor(new byte[]{(byte)0,(byte)0,(byte)0}));
                    cellStyle.setBorderLeft(BorderStyle.THIN);
                    cellStyle.setLeftBorderColor(new XSSFColor(new byte[]{(byte)0,(byte)0,(byte)0}));
                    cellStyle.setBorderRight(BorderStyle.THIN);
                    cellStyle.setRightBorderColor(new XSSFColor(new byte[]{(byte)0,(byte)0,(byte)0}));
                    cellStyle.setAlignment(HorizontalAlignment.CENTER);
                    cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                    row.createCell(1).setCellStyle(cellStyle);
                    row.createCell(2).setCellStyle(cellStyle);
                    row.createCell(3).setCellStyle(cellStyle);
                    row.createCell(4).setCellStyle(cellStyle);
                    row.createCell(5).setCellStyle(cellStyle);
                    row.createCell(6).setCellStyle(cellStyle);
                }
                row.getCell(1).setCellValue(startTime.toLocalDate().toString());
                row.getCell(2).setCellValue(dayVo.getTurnover()+"");
                row.getCell(3).setCellValue(dayVo.getValidOrderCount()+"");
                row.getCell(4).setCellValue(dayVo.getOrderCompletionRate()+"");
                row.getCell(5).setCellValue(dayVo.getUnitPrice()+"");
                row.getCell(6).setCellValue(dayVo.getNewUsers()+"");
                i++;
                startTime=startTime.plusDays(1);
            }
            // 写入到response的输出流
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
            // 关闭流
            workbook.close();
            outputStream.close();
        }catch (Exception e){
            log.error(e.getMessage(), e);
            throw new BaseException("文件下载异常");
        }
    }
}
